QReadWriteLock: fix data race on the d_ptr members
authorDebian Qt/KDE Maintainers <debian-qt-kde@lists.debian.org>
Wed, 31 Dec 2025 10:28:57 +0000 (13:28 +0300)
committerDmitry Shachnev <mitya57@debian.org>
Wed, 31 Dec 2025 10:28:57 +0000 (13:28 +0300)
Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit?id=80d01c4ccb697b9d
Last-Update: 2025-12-14

The loadRelaxed() at the beginning of tryLockForRead/tryLockForWrite
isn't enough to bring us the non-atomic write of the recursive bool.
Same issue with the std::mutex itself.

Gbp-Pq: Name qreadwritelock_data_race.diff

src/corelib/thread/qreadwritelock.cpp

index 9dd8503116197f77db01d3f1a37bea6d123f2dc2..84d73444be45fb6f54fe9ffc5f32cb8c8f70aa7d 100644 (file)
@@ -258,7 +258,10 @@ bool QReadWriteLock::tryLockForRead(int timeout)
             d = val;
         }
         Q_ASSERT(!isUncontendedLocked(d));
-        // d is an actual pointer;
+        // d is an actual pointer; acquire its contents
+        d = d_ptr.loadAcquire();
+        if (!d || isUncontendedLocked(d))
+            continue;
 
         if (d->recursive)
             return d->recursiveLockForRead(timeout);
@@ -365,7 +368,10 @@ bool QReadWriteLock::tryLockForWrite(int timeout)
             d = val;
         }
         Q_ASSERT(!isUncontendedLocked(d));
-        // d is an actual pointer;
+        // d is an actual pointer; acquire its contents
+        d = d_ptr.loadAcquire();
+        if (!d || isUncontendedLocked(d))
+            continue;
 
         if (d->recursive)
             return d->recursiveLockForWrite(timeout);